package cn.tedu.straw.portal.service.impl;

import cn.tedu.straw.portal.Schedule.CacheSchedule;
import cn.tedu.straw.commons.dto.QuestionDTO;
import cn.tedu.straw.portal.kafka.message.CreateQuestionMessage;
import cn.tedu.straw.portal.mapper.*;
import cn.tedu.straw.commons.model.*;
import cn.tedu.straw.portal.service.IQuestionService;
import cn.tedu.straw.portal.service.ITagService;
import cn.tedu.straw.portal.service.ex.*;
import cn.tedu.straw.commons.vo.QuestionListItemVO;
import cn.tedu.straw.commons.vo.QuestionVO;
import cn.tedu.straw.commons.vo.StatisticsVO;
import cn.tedu.straw.commons.vo.TagVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Array;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author tedu.cn
 * @since 2020-07-22
 */
@Service
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements IQuestionService {
    @Autowired
    private QuestionMapper questionMapper;
    @Autowired
    private QuestionTagMapper questionTagMapper;
    @Autowired
    private UserCollectionMapper userCollectionMapper;
    @Autowired
    private UserQuestionMapper userQuestionMapper;
    @Autowired
    private ITagService tagService;
    @Autowired
    private AnswerMapper answerMapper;
    @Autowired
    private Gson gson;
    @KafkaListener(topics = "CREATE_QUESTION")
    public void create(ConsumerRecord<String, String> record) {
        String messageJson = record.value();
        CreateQuestionMessage message = gson.fromJson(messageJson, CreateQuestionMessage.class);
        create(message.getQuestionDTO(), message.getUserId(), message.getUserNickName());
    }

    @Override
    @Transactional
    public void create(QuestionDTO questionDTO, Integer userid, String userNickname) {
        LocalDateTime now = LocalDateTime.now();



        String tagIdsStr = Arrays.toString(questionDTO.getTagIds());    // [2, 7, 9]
        tagIdsStr = tagIdsStr.substring(1, tagIdsStr.length() - 1);     // 2, 7, 9

        Question question = new Question();
        question.setTitle(questionDTO.getTitle());
        question.setContent(questionDTO.getContent());
        question.setUserId(userid);
        question.setUserNickName(userNickname);
        question.setStatus(0);
        question.setHits(0);
        question.setIsPublic(1);
        question.setCreatedTime(now);
        question.setModifiedTime(now);
        question.setTagIds(tagIdsStr);
        int rows = questionMapper.insert(question);
        if (rows!=1){
            throw new InsertException("发布问题失败!当前服务器忙,请稍后尝试");
        }

        for (Integer tagId:questionDTO.getTagIds()){
            QuestionTag questionTag = new QuestionTag()
                    .setQuestionId(question.getId())
                    .setTagId(tagId);
             rows = questionTagMapper.insert(questionTag);
            if (rows!=1){
                throw new InsertException("发布问题失败!当前服务器忙,请稍后尝试");
            }
        }

        for (Integer teacherId : questionDTO.getTeacherIds()){
            UserQuestion userQuestion =new UserQuestion()
                    .setQuestionId(question.getId())
                    .setUserId(teacherId)
                    .setCreatedTime(now);
            rows = userQuestionMapper.insert(userQuestion);
            if (rows!=1){
                throw new InsertException("发布问题失败!当前服务器忙,请稍后尝试");
            }
        }


    }
    private List<QuestionListItemVO> MostHits=new CopyOnWriteArrayList<>();



    @Value("${project.question-list.page-size}")
    private Integer pageSize;

    @Override
    public List<QuestionListItemVO> getMostHits() {
        if(MostHits.isEmpty()){
            synchronized (CacheSchedule.lock_CANCHE){
                if (MostHits.isEmpty()){
                    MostHits.addAll(questionMapper.findMostHits());
                }
            }
        }
        return MostHits;
    }

    @Override
    public List<QuestionListItemVO> getCachedMostHits() {

        return MostHits;
    }




    @Override
    public PageInfo<QuestionVO> getQuestionByUserId(Integer userId,Integer type,Integer page) {
        //设置分页参数
        PageHelper.startPage(page,pageSize);
        // 调用持久层方法查询问题列表，该列表中的数据只有标签的id，并不包括标签数据
        List<QuestionVO> questions;
        if (type == User.TYPE_STUDENT) {
            questions = questionMapper.findListByUserId(userId);
        } else {
            questions = questionMapper.findTeacherQuestions(userId);
        }
        // 遍历以上列表，取出每个问题中记录的标签的ids，并根据这些id从缓存中取出TagVO封装到QuestionVO对象中
        for (QuestionVO question : questions) {
            // 取出标签的id
            String tagIdsStr = question.getTagIds(); // 1, 2, 3
            // 拆分
            String[] tagIds = tagIdsStr.split(", ");
            // 创建用于存放若干个标签的集合
            question.setTags(new ArrayList<>());
            // 遍历数组，从缓存中找出对应的TagVO
            for (String tagId : tagIds) {
                // 从缓存中取出对应的TagVO
                Integer id = Integer.valueOf(tagId);
                TagVO tag = tagService.getTagVOById(id);
                // 将取出的TagVO添加到QuestionVO对象中
                question.getTags().add(tag);
            }
        }
        // 返回
        return new PageInfo<QuestionVO>(questions);
    }

    /**
     * 根据标签id获取标签（TagVO）数据的集合
     *
     * @param tagIdsStr 由若干个标签id组成的字符串，各id之间使用 , 分隔
     * @return 签（TagVO）数据的集合
     */
    private List<TagVO> getTagsByIds(String tagIdsStr) {
        // 拆分
        String[] tagIds = tagIdsStr.split(", ");
        // 创建用于存放若干个标签的集合
        List<TagVO> tags = new ArrayList<>();
        // 遍历数组，从缓存中找出对应的TagVO
        for (String tagId : tagIds) {
            // 从缓存中取出对应的TagVO
            Integer id = Integer.valueOf(tagId);
            TagVO tag = tagService.getTagVOById(id);
            // 将取出的TagVO添加到QuestionVO对象中
            tags.add(tag);
        }
        // 返回
        return tags;
    }

    @Override
    public QuestionVO getQuestionById(Integer id) {
        // 实现过程中，先通过持久层查询数据，并判断查询结果是否为null，如果为null，则抛出异常。
        QuestionVO questionVO = questionMapper.findById(id);
        if (questionVO == null) {
            throw new QuestionNotFoundException("获取问题详情失败，尝试访问的数据不存在！");
        }

        // 根据查询结果中的tagIds确定tags的值。
        questionVO.setTags(getTagsByIds(questionVO.getTagIds()));

        // 返回查询结果
        return questionVO;
    }

    @Transactional
    public QuestionVO updateQuestionAnswer(Integer id,Integer userId){
        Answer answer = answerMapper.selectById(id);
        Integer questionId = answer.getQuestionId();
        Question question = questionMapper.selectById(questionId);


        if (!question.getUserId().equals(userId)) {
            // 如果这2个条件都不符合，则不允许修改，抛出PermissionDeniedException
            throw new PermissionDeniedException("采纳回答失败！仅发布者修改此条评论！");
        }

        int[] ints = answerMapper.findquestionId(questionId);
        for (int i = 0; i < ints.length; i++) {
            if(ints[i]==1){
                throw new UpdateException("这个问题已有答案被采纳");
            }

        }

        Integer rows = questionMapper.updateQuestion(questionId, Question.Status.RESOLVED);
        if (rows!=1){
            throw new UpdateException("修改问题状态失败");
        }
        Integer rows1 = questionMapper.updatAnswer(id, Answer.Status.ACCEPTED);
        if (rows1!=1){
            throw new UpdateException("修改回答状态失败");
        }
        QuestionVO questionVO = new QuestionVO();
        String[] texts = Question.Status.TEXTS;
        questionVO.setQuestiontexts(texts[Question.Status.RESOLVED]);
        String[] texts1 = Answer.Status.TEXTS;
        questionVO.setAnswertexts(texts1[Answer.Status.ACCEPTED]);


        return questionVO;
    }

    @Override
    public StatisticsVO statistics(Integer userId, String nickname) {
        QueryWrapper<Answer> answerQueryWrapper = new QueryWrapper<>();
        answerQueryWrapper.eq("user_id", userId);
        Integer answer = answerMapper.selectCount(answerQueryWrapper);

        QueryWrapper<Question> questionQueryWrapper = new QueryWrapper<>();
        questionQueryWrapper.eq("user_id", userId);
        Integer question = questionMapper.selectCount(questionQueryWrapper);

        QueryWrapper<UserCollection> userCollectionQueryWrapper = new QueryWrapper<>();
        userCollectionQueryWrapper.eq("user_id", userId);
        Integer userCollect = userCollectionMapper.selectCount(userCollectionQueryWrapper);

        QueryWrapper<UserQuestion> userQuestionQueryWrapper1 = new QueryWrapper<>();
        userQuestionQueryWrapper1.eq("user_id", userId);
        Integer userQuest = userQuestionMapper.selectCount(userQuestionQueryWrapper1);



        StatisticsVO statistics=new StatisticsVO();
        statistics.setNickName(nickname);
        statistics.setAnswer(answer);
        statistics.setQuestion(question);
        statistics.setCollect(userCollect);
        statistics.setTask(userQuest);
        return statistics;
    }

    @Override
    public Integer updateQuestion(Integer id) {
        Integer integer = questionMapper.updateQuestion(id, Question.Status.TO_BE_SOLVED);
        if (integer!=1){
            throw new UpdateException("修改状态失败");
        }
        return integer;
    }

    @Override
    public Integer updateQuestion(Integer id, Integer Status) {
        Integer rows = questionMapper.updateQuestion(id, Status);
        if (rows!=1){
            throw new UpdateException("修改问题状态失败");
        }
        return rows;
    }

    @Override
    public Integer updatAnswer(Integer id, Integer Status_of_accept) {
        Integer rows = questionMapper.updatAnswer(id, Status_of_accept);
        if (rows!=1){
            throw new UpdateException("修改回答状态失败");
        }
        return rows;
    }


}
